/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dao;

import java.util.ArrayList;
import pojo.Message;
import pojo.Property;
import pojo.Row;

/**
 *
 * @author HoangLiem
 */
public class ExecInsertQuery {

    public static boolean validateAndExecQuery(String databaseName, String query, Message message) {
        boolean result = true;
        try {
            String tableName = "";
            String originalValues = "";
            ArrayList<String> propertyNames = new ArrayList<String>();
            ArrayList<String> propertyData = new ArrayList<String>();

            String queryFirst = query;
            queryFirst = ExecQuery.trimMoreSpace(queryFirst);
            queryFirst = ExecQuery.standardOutsideOfParentheses(queryFirst);
            queryFirst = ExecQuery.standardInsideOfParentheses(queryFirst);

            String[] s = queryFirst.split(" ");
            if (s.length < 5) {// phai it nhất co 5 đoan trong cau insert
                message.setMessage("Query not enough components");
                return false;
            }
            //kiem tra ton tai insert, la phan tu s[0]
            if (!s[0].toLowerCase().trim().equals("insert")) {
                message.setMessage("Component 'insert' not exist");
                return false;
            }
            //kiem tra into
            if (!s[1].toLowerCase().trim().equals("into")) {
                message.setMessage("Error in component 'into'");
                return false;
            }
            //Kiem tra ton  tại ten bang
            ArrayList<String> tableNames = ExecTableXML.getNamesOfTable(databaseName);
            if (!ExecXML.isExistedString(tableNames, s[2].toLowerCase().trim())) {
                message.setMessage("Table '" + tableName + "' does not exists");
                return false;
            } else {
                tableName = s[2].toLowerCase().trim();
            }
            //kiem tra có thành phần values, s[3], hoac s[4],
            //neu s[3] khong phai 'values' thi s[3] là thành phần thuộc tính hoac values sai
            String fields = "";
            if (!s[3].toLowerCase().trim().equals("values")) {
                //tiep tuc kiem tra thanh phan 4 xem co values khong
                if (!s[4].toLowerCase().trim().equals("values")) {
                    message.setMessage("Error component 'values'");
                    return false;
                } else {
                    originalValues = s[4];
                }
                //Neu s[4] la thanh phan values thi s[3] phai la thanh phan thuoc tinh sau table
                fields = s[3];
                //Kiem tra thanh phan thuoc tinh hop le, fields dạng (a,b,c)
                fields = fields.toLowerCase().trim();
                if (fields.length() < 3 || fields.charAt(0) != '(' || fields.charAt(fields.length() - 1) != ')') {
                    message.setMessage("Error in field name of table");
                    return false;
                } else {
                    StringBuilder sb = new StringBuilder(fields);
                    sb.deleteCharAt(0);// bỏ dấu (
                    sb.deleteCharAt(sb.length() - 1);//bỏ dấu )
                    //split theo dấu phẩy
                    fields = sb.toString();
                    ArrayList<String> splitFields = ExecQuery.splitComma(fields);
                    if (splitFields.size() > 0) {
                        for (int i = 0; i < splitFields.size(); i++) {
                            String field = splitFields.get(i);
                            if (!ExecTableXML.isExistedFieldName(databaseName, tableName, field)) {
                                message.setMessage("Not existed '" + field + "' in '" + tableName + "'");
                                return false;
                            } else {
                                propertyNames.add(field);
                            }
                        }
                    } else {
                        message.setMessage("Error in field name of table");
                        return false;
                    }
                }

            } else {
                originalValues = s[3];
                propertyNames = ExecTableXML.getAllFieldsFromTable(databaseName, tableName);
            }
            //Kiem tra thành phần dữ liệu sau values.
            //Lấy từ sau values đến hết,  originalValues luu chinh xac thanh phan values
            String values = query.substring(query.indexOf(originalValues));
            values = values.replace(originalValues, "").trim();

            if (values.length() > 3) {
                values = ExecQuery.trimCharsFirstEnd(values);//xóa ( va )
                ArrayList<String> splitValues = ExecQuery.splitComma(values);
                if (splitValues.size() > 0) {
                    if (splitValues.size() != propertyNames.size()) {
                        message.setMessage("Size of data component is not equal size of fields");
                        return false;
                    }
                    for (int i = 0; i < splitValues.size(); i++) {
                        //kiem tra phu hop voi type tung cot
                        String value = splitValues.get(i).trim();
                        Property pro = ExecTableXML.getFieldOfTable(databaseName, tableName, propertyNames.get(i));
                        if (pro == null) {
                            message.setMessage("Error when get info of '" + propertyNames.get(i) + "'");
                            return false;
                        }
                        if (pro.getType().equalsIgnoreCase("string")) {
                            //kiem tra la chuoi
                            if (value.length() >= 2) {
                                if (value.charAt(0) == '\'' && value.charAt(value.length() - 1) == '\'') {
                                    value = ExecQuery.trimCharsFirstEnd(value);
                                    if (!value.contains("'")) {
                                        if (value.length() > pro.getLength()) {
                                            message.setMessage("Error data ' at '" + value + "', length data greater length in field");
                                            return false;
                                        }
                                        propertyData.add(value);
                                    } else {
                                        message.setMessage("Error ' at '" + value + "'");
                                        return false;
                                    }

                                } else {
                                    message.setMessage("Error ' at '" + value + "'");
                                    return false;
                                }
                            } else {
                                message.setMessage("Error at '" + value + "'");
                                return false;
                            }
                        } else {
                            //kiem tra la so nguyen
                            if (pro.getType().equalsIgnoreCase("integer")) {
                                if (ExecXML.isInteger(value)) {
                                    propertyData.add(value);
                                } else {
                                    message.setMessage("Error at '" + value + "'");
                                    return false;
                                }
                            } else {//kiem tra so thuc
                                if (ExecXML.isReal(value)) {
                                    propertyData.add(value);
                                } else {
                                    message.setMessage("Error at '" + value + "'");
                                    return false;
                                }
                            }
                        }
                    }
                } else {
                    message.setMessage("error component data");
                    return false;
                }

            } else {
                message.setMessage("Error after component 'values'");
                return false;
            }

            //Nếu qua được thành phần này thì tới thêm data, 
            //ta đã lấy đc tableName, propertyNames trong cau truy van, propertyData can them
            //Dem so cot trong table
            if (propertyNames == null && propertyNames.isEmpty()) {
                message.setMessage("Error in get property names");
                return false;
            }
            if (propertyData == null && propertyData.isEmpty()) {
                message.setMessage("Error in get data");
                return false;
            }
            if (propertyNames.size() != propertyData.size()) {
                message.setMessage("Elements in fields and elements data not equal");
                return false;
            }
            ArrayList<String> tableFields = ExecTableXML.getAllFieldsFromTable(databaseName, tableName);
            if (tableFields != null && !tableFields.isEmpty()) {
                String[] data = new String[tableFields.size()];
                for (int d = 0; d < data.length; d++) {
                    data[d] = "";
                }
                for (int i = 0; i < propertyNames.size(); i++) {
                    //lay vi tri property để biết set cho nào trong data
                    int proPos = ExecPropertyXML.getActualPosition(databaseName, tableName, propertyNames.get(i));
                    if (proPos != -1) {
                        data[proPos] = propertyData.get(i);

                    } else {
                        message.setMessage("Error when processing set data at '" + propertyNames.get(i) + "'");
                        return false;
                    }
                }
                Row row = new pojo.Row();
                for (int i = 0; i < data.length; i++) {
                    row.setValueString(data[i]);
                }
                if (ExecRowXML.isExistedIdData(databaseName, tableName, row)) {
                    message.setMessage("Existed ID value in '" + tableName + "'");
                    return false;
                }
                if (!ExecRowXML.isExistedForeignKeyData(databaseName, tableName, row)) {
                    message.setMessage("Not Existed foreign key value");
                    return false;
                }
                if (!ExecRowXML.isValidatedData(databaseName, tableName, row)) {
                    message.setMessage("Data not validated with type of field");
                    return false;
                }
                if (!ExecRowXML.isNotNullData(databaseName, tableName, row)) {
                    message.setMessage("Data is not 'NOT NULL'");
                    return false;
                }
                if (!ExecRowXML.isUniqueData(databaseName, tableName, row)) {
                    message.setMessage("Data is not 'UNIQUE'");
                    return false;
                }
                //bat dau them
                boolean insertResult = ExecRowXML.insertRow(databaseName, tableName, row);
                if (insertResult) {
                    message.setMessage("Insert data to '" + tableName + "' successfully");
                } else {
                    message.setMessage("Failed when processing insert data to '" + tableName + "'");
                    return false;
                }
            } else {
                message.setMessage("Error when processing insert data");
                return false;
            }

        } catch (Exception ex) {
            message.setMessage("Error when insert");
            result = false;
        }
        return result;
    }
}
